package com.fqcar.fqdf.core.http;

import com.alibaba.fastjson.JSON;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.RetryPolicy;
import com.android.volley.toolbox.HttpHeaderParser;
import com.fqdf.framework.android.util.LogUtil;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ResponseTOptRequest<T> extends Request<T> {

    private Map<String, String> params = new HashMap<>();
    private final static RetryPolicy mRetryPolicy = new DefaultRetryPolicy(3 * 60 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    private HashMap<String, String> headers = new HashMap<>();
    private final Listener<T> responseEntityListener;

    private Type convType;


    public ResponseTOptRequest(String url) {
        this(url, null);
    }

    public ResponseTOptRequest(String url, Listener<T> listener) {
        this(url, null, listener);
    }

    public ResponseTOptRequest(String url, Map<String, String> params, Map<String, String> headers) {
        this(url, params, headers, null, null);
    }

    public ResponseTOptRequest(String url, Map<String, String> params, Map<String, String> headers, Listener<T> listener) {
        this(url, params, headers, listener, null);
    }

    public ResponseTOptRequest(String url, Map<String, String> params, Listener<T> listener) {
        this(url, params, null, listener, null);
    }

    public ResponseTOptRequest(String url, Map<String, String> paramsMap, Map<String, String> headersMap,
                               Listener<T> resultSuccessListener, Response.ErrorListener errorListener) {
        super(Method.POST, url, errorListener);
        if (paramsMap != null) {
            params.putAll(paramsMap);
            removeEmptyParamKeyAndValue(params);
        }
        if (headersMap != null) {
            headers.putAll(headersMap);
            removeEmptyParamKeyAndValue(headers);
        }

        responseEntityListener = resultSuccessListener;

        Type[] typeArr = resultSuccessListener.getClass().getGenericInterfaces();
        ParameterizedType parameterizedType = (ParameterizedType) typeArr[0];
        convType = parameterizedType.getActualTypeArguments()[0];

        setShouldCache(false);
        setRetryPolicy(mRetryPolicy);
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return headers;
    }

    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return this.params;
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {

        try {
            String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));

            LogUtil.json(jsonString);
            LogUtil.d(convType);
            T request = JSON.parseObject(jsonString, convType);

            LogUtil.d(request);
            return Response.success(request, HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(T response) {
        if (responseEntityListener != null) {
            responseEntityListener.onResponse(response);
        }
    }

    /**
     * 检查参数是否包含null的key或者value
     *
     * @return
     */
    private void removeEmptyParamKeyAndValue(Map<String, String> originMap) {
        List<String> prepareToRemoveKeys = new ArrayList<>();
        for (Iterator<String> iter = originMap.keySet().iterator(); iter.hasNext(); ) {
            String key = iter.next();
            String value = originMap.get(key);
            if (key == null || value == null) {
                prepareToRemoveKeys.add(key);
            }
        }
        if (!prepareToRemoveKeys.isEmpty()) {
            for (String prepareToRemoveKey : prepareToRemoveKeys) {
                originMap.remove(prepareToRemoveKey);
            }
        }
    }

}